package cn.jc.myfile.common.util;

import cn.jc.myfile.common.completable.AutoFill;
import cn.jc.myfile.common.completable.AutoFillUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanCopier;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Slf4j
public class BeanCopyUtil {
    /**
     * 使用缓存提高效率
     */
    private static final ConcurrentHashMap<String, BeanCopier> COPIER_CACHE = new ConcurrentHashMap<>();

    /**
     * 自动填充工具
     */
    private static AutoFillUtil autoFillUtil;

    /**
     * 私有构造方法
     */
    private BeanCopyUtil() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }

    /**
     * 复制list
     *
     * @param sourceList  sourceList
     * @param targetClass targetClass
     * @param <S>         源类型
     * @param <T>         目标类型
     * @return 目标类list
     */
    public static <S, T> List<T> copyList(List<S> sourceList, Class<T> targetClass) {
        return sourceList.stream().map(
               source -> copy(source, targetClass)).collect(Collectors.toList());
    }


    /**
     * 复制并新建类
     *
     * @param source      source
     * @param targetClass targetClass
     * @param <S>         源类型
     * @param <T>         目标类型
     * @return 目标类
     */
    public static <S, T> T copy(S source, Class<T> targetClass) {
        try {
            T instance = targetClass.getDeclaredConstructor().newInstance();
            return copy(source, instance);
        } catch (Exception e) {
            log.error("创建对象异常:", e);
            return null;
        }
    }

    /**
     * 复制方法
     *
     * @param source source
     * @param target target
     * @param <S>    源类型
     * @param <T>    目标类型
     * @return 目标类
     */
    public static <S, T> T copy(S source, T target) {
        if (source != null) {
            try {
                String baseKey = generateKey(source.getClass(), target.getClass());
                BeanCopier copier;
                if (COPIER_CACHE.contains(baseKey)) {
                    copier = COPIER_CACHE.get(baseKey);
                } else {
                    copier = BeanCopier.create(source.getClass(), target.getClass(), false);
                    COPIER_CACHE.put(baseKey, copier);
                }
                copier.copy(source, target, null);
                fill(target);
            } catch (Exception e) {
                log.error("复制对象属性异常:{}", e.getMessage());
            }
        }
        return target;
    }

    /**
     * 生成缓存key
     *
     * @param source source
     * @param target target
     * @return 目标类
     */
    private static String generateKey(Class<?> source, Class<?> target) {
        return String.format("%s|%s", source.toString(), target.toString());
    }

    /**
     * 填充方法
     *
     * @param t   实体类
     * @param <T> 实体类
     */
    private static <T> void fill(T t) {
        if (t instanceof AutoFill) {
            if (autoFillUtil == null) {
                autoFillUtil = cn.jc.myfile.common.util.SpringBeanUtil.getBean(AutoFillUtil.class);
            }
            autoFillUtil.fill((AutoFill) t);
        }
    }


}
